<?php

namespace app\wechat\models;

use common\models\CircuitAddress;
use common\models\LogHelper;
use common\models\Order;
use common\models\PointTime;
use common\models\Site;
use common\models\UserRebate;
use Exception;
use platform\models\SysModel;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Exceptions\LocalCacheException;
use yii\base\InvalidArgumentException;
use app\wechat\core\BaseModel;
use cm;
use Yii;
use yii\db\Expression;
use yii\helpers\Json;
use yii\helpers\Url;

class OrderModel extends BaseModel
{
    /*
    *购票须知
    */
    public function actionBuynotice(){
        $resdata = $this->getNoticeData('sys_buy_notice');
        Cm::$res->susess($resdata);
    }

    /*
    *退票须知
    */
    public function actionRetreatnotice(){
        $resdata = $this->getNoticeData('sys_retreat_notice');
        Cm::$res->susess($resdata);
    }
    /*
    *分销规则
    */
    public function actionRebatenotice(){
        $resdata = $this->getNoticeData('sys_rebate_notice');
        Cm::$res->susess($resdata);
    }

    /*
    *开单
    */
    public function actionAddorder(){
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $pt_id = (int)Cm::$req->post('pt_id', ['null', 'empty', 'default' => 0]);
        $contacts = Cm::$req->post('contacts', ['null', 'empty', 'default' => '']);
        $contacts_num = (int)Cm::$req->post('contacts_num', ['null', 'empty', 'default' => 0]);
        $contactsarr = empty($contacts) ? [] : json_decode($contacts,true);
        if(empty($contactsarr)){
            Cm::$res->error("请添加乘客信息");
        }
        if($contacts_num != count($contactsarr)){
            Cm::$res->error("乘客人数信息错误");
        }
        $time = time();
        $timestr = date("Y-m-d H:i:s",$time);
        $point=PointTime::findOne($pt_id);
        if(!$point){
            Cm::$res->error("没有找到该班次!");
        }
        $ca_id=$point->ca_id;
        $shiftinfo = Cm::$db->one("SELECT a.id,a.circuit_id,a.presaletime,a.closingtime,a.ticket_price,b.name,b.rebate_status,b.rebate_type,b.rebate 
    from shift a 
    INNER JOIN circuit b ON a.circuit_id=b.id 
    INNER JOIN circuit_address ca ON ca.circuit_id=b.id
    WHERE a.id={$id} AND a.status=1 AND b.status=1 AND ca.id={$ca_id} AND ca.type=1 AND ca.is_del=1 ");
        if(empty($shiftinfo)){
            Cm::$res->error("没有找到该班次");
        }
        $e_id=CircuitAddress::find()->andWhere(['circuit_id'=>$shiftinfo['circuit_id'],'type'=>CircuitAddress::TYPE_GETOFF,'is_del'=>CircuitAddress::IS_DEL_NO])
            ->select('id')->scalar();
        if(empty($e_id))Cm::$res->error("没有找到该班次");
        if(strtotime($shiftinfo['closingtime'])<$time){
            Cm::$res->error("该班次已停售");
        }
        $user = Cm::$db->one("SELECT id,telephone,bind_uid FROM user WHERE openid='{$this->openid}'");
        if(empty($user['id'])){
            Cm::$res->error('参数错误');
        }
        $isok = 1;
        $telephone = '';
        $contactsids = [];
        $isrepeat = 0;
        foreach ($contactsarr as $key => $value) {
            if(empty($value['name']) || empty($value['telephone']) || empty($value['idcard']) || empty($value['id']) || empty($value['contacts_id'])){
                $isok = 0;
                break;
            }
            if(!in_array($value['contacts_id'], $contactsids)){
                $contactsids[] = $value['contacts_id'];
            }else{
                $isrepeat = 1;
                break;
            }
            $telephone = $key == 0 ? $value['telephone'] : $telephone;
        }
        if($isok == 0){
            Cm::$res->error('乘客信息不正确');
        }
        if($isrepeat == 1){
            Cm::$res->error('不能重复添加乘客');
        }

        $config = Cm::$db->all("SELECT `key`,`value` FROM config_setting WHERE `group`='sys' AND `key` IN ('sys_service_charge','sys_premium') ");
        $service_charge = 0;
        $premium = 0;
        if(!empty($config)){
            foreach ($config as $key => $vs) {
                if($vs['key'] == 'sys_service_charge'){
                    $service_charge = sprintf("%.2f",$vs['value']*$contacts_num);
                }else if($vs['key'] == 'sys_premium'){
                    $premium = sprintf("%.2f",$vs['value']*$contacts_num);
                }
            }
        }
        $price = sprintf("%.2f",$shiftinfo['ticket_price']*$contacts_num);
        $order_price = $price + $premium + $service_charge;

        $order_number = $this->getorderanumber($id,$shiftinfo['circuit_id'],$timestr);
        $order_number = "M".$order_number;
        $rebate_price=0;
        $bind_uid=empty($user['bind_uid'])?0:$user['bind_uid'];
        if(!empty($shiftinfo['rebate_status'])&&$bind_uid){
            if($shiftinfo['rebate_type']==SysModel::REBATE_TYPE_RATIO){
                if($shiftinfo['rebate']>100||$shiftinfo['rebate']<0)Cm::$res->error('分销比列设置错误,联系系统管理员');
                $rebate_price=sprintf("%.2f",$price*$shiftinfo['rebate']/100);
            }else{
                if($shiftinfo['rebate']<0)Cm::$res->error('分销金额设置错误,联系系统管理员');
                $rebate_price=$shiftinfo['rebate'];
            }
        }

        if($rebate_price>$price)Cm::$res->error('分销金额设置大于车票金额,联系系统管理员修改！');

        $orderdata = [
            'order_number' => $order_number,
            'shift_id'=> $id,
            'circuit_id' => $shiftinfo['circuit_id'],
            's_id'=>$ca_id,
            'e_id'=>$e_id,
            'p_id'=>$pt_id,
            'order_status' => 0,
            'ridership' => count($contactsarr),
            'order_price' => $order_price,
            'price' => $price,
            'premium' => $premium,
            'service_charge' => $service_charge,
            'source' => 1,
            'user_id' => $user['id'],
            'user_telephone' => empty($user['telephone']) ? $telephone : $user['telephone'],
            'bind_uid'=>$bind_uid,
            'rebate_status'=> $shiftinfo['rebate_status'],
            'rebate_type'=> $shiftinfo['rebate_type'],
            'rebate'=> $shiftinfo['rebate'],
            'rebate_price'=> $rebate_price,
            'status'=>1,
            'addtime' => $timestr,
            'updatetime' => $timestr
        ];

        $orderid = Cm::$db->insert("order", $orderdata);
        $config = Yii::$app->params['wechat']['open'];
        $paySdk = Cm::$libs->wechat->pay($config['appid']);
        $goods = [
            "body" => '商品购买',
            "attach" => 'order',
            "out_trade_no" => $order_number,
            "total_fee" => $order_price * 100,
            "goods_tag" => $shiftinfo['name'],
            "openid" => $this->openid,
            "notify_url" => BASE_URL . Url::to(['/wechat/order/notify'])
        ];
        $payRes = $paySdk->jspay($goods);
        if (!$payRes['flag']) {
            Cm::$res->error($payRes['msg']);
        }
        if($orderid){
            foreach ($contactsarr as $key => $value) {
                $mdata = [
                    'order_id'=> $orderid,
                    'shift_id'=> $id,
                    'circuit_id' => $shiftinfo['circuit_id'],
                    'user_id'=> $user['id'],
                    'contacts_id' => $value['contacts_id'],
                    'name' => $value['name'],
                    'telephone' => $value['telephone'],
                    'id_card' => $value['idcard'],
                    'status' => 1,
                    'addtime' => $timestr,
                    'updatetime' => $timestr
                ];
                Cm::$db->insert("order_passenger", $mdata);
            }
            $this->addordercode($orderid);
            Cm::$res->susess(['id'=>$orderid,'order_number'=>$order_number,'price'=>$price,'order_price'=>$order_price,'premium'=>$premium,'service_charge'=>$service_charge,'pay' => $payRes['data']],'保存成功');
        }else{
            Cm::$res->error('保存失败');
        }
    }

    /*
    *订单待支付支付
    */
    public function actionPayorder(){
        $this->refreshorder();
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $where = " a.id={$id} AND u.openid='{$this->openid}'";
        $info = Cm::$db->one("SELECT a.id,a.order_number,a.order_price,a.order_status,a.status,c.name,a.pay_status
				FROM `order` a 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where}");
        if(empty($info)){
            Cm::$res->error("订单不存在");
        }
        if($info['order_status'] == 5){
            Cm::$res->error("订单已失效,无法在支付");
        }
        if($info['status'] != 1){
            $strarr = [0=>'取消',2=>'删除',3=>'改签',4=>'退款'];
            Cm::$res->error("订单已".$strarr[$info['status']].",无法在支付");
        }
        if($info['order_status'] != 0){
            Cm::$res->error("订单已支付,无法在支付");
        }

        if($info['pay_status'] != 0){
            Cm::$res->error("订单已支付,无法在支付");
        }

        $config = Yii::$app->params['wechat']['open'];
        $paySdk = Cm::$libs->wechat->pay($config['appid']);
        $goods = [
            "body" => '商品购买',
            "attach" => 'order',
            "out_trade_no" => $info['order_number'],
            "total_fee" => $info['order_price'] * 100,
            "goods_tag" => $info['name'],
            "openid" => $this->openid,
            "notify_url" => BASE_URL . Url::to(['/wechat/order/notify'])
        ];
        $payRes = $paySdk->jspay($goods);
        if (!$payRes['flag']) {
            Cm::$res->error($payRes['msg']);
        }
        Cm::$res->susess(['pay' => $payRes['data']],'');
    }

    /*
    *订单支付回调
    */
    public function actionNotify(){
        $xml = "";
        if (isset($GLOBALS['HTTP_RAW_POST_DATA'])){
            $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        }

        $this->notifylog($xml,'notify-GLOBALS');

        if(empty($xml)){
            $xml = file_get_contents('php://input');
            $this->notifylog($xml,'notify-input');
        }

        if (empty($xml)) {
            $this->notifylog("支付回调无参数");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!$data) {
            $this->notifylog("没有数据");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }

        if (!$this->checkSign($data)) {
            $this->notifylog("签名失败");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>";
            exit;
        }

        $flag = false;
        if (isset($data['result_code']) && isset($data['return_code'])) {
            if ($data['result_code'] == "SUCCESS" && $data['return_code'] == "SUCCESS") {
                $number = isset($data['out_trade_no']) ? $data['out_trade_no'] : '';
                if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,pay_status,bind_uid,rebate_status,rebate_type,rebate,rebate_price,rebate_issue FROM `order` WHERE order_number='{$number}' AND pay_status=0");
                    if (isset($info['id'])) {
                        if ($info['pay_status']==0) {
                            //更改支付状态
                            $time = date("Y-m-d H:i:s",time());
                            $pay_price = $data['cash_fee']/100;
                            Cm::$db->update("order", ["order_status"=>1,"updatetime"=>$time,"pay_type"=>1,"pay_status" => 1, "pay_time" => $time,'pay_price'=>$pay_price], "id={$info['id']}");
                            if($info['bind_uid']&&$info['rebate_status']==Order::REBATE_STATUS_YES&&$info['rebate_price']>0
                                &&!UserRebate::find()->andWhere(['order_id'=>$info['id']])->exists()){
                                $model=new UserRebate();
                                $model->uid=$info['bind_uid'];
                                $model->type=UserRebate::TYPE_GET;
                                $model->order_id=$info['id'];
                                $model->money=$info['rebate_price'];
                                $model->date_ym=date("Ym",time());
                                $model->date_ymd=date("Ymd",time());
                                $model->status=UserRebate::STATUS_PASS;
                                if(!$model->save())LogHelper::Logging(Yii::getAlias("@common/runtime/佣金在途失败/" . date("Ymd") . ".txt"), Json::encode($info));
                            }
                            //发送购买成功通知
                            $TemplateData = [
                                'openid' => $data['openid'],
                                'order_id' => $info['id']
                            ];
                            Cm::$libs->wechat->sendTemplate('order',$TemplateData);
                        }else{
                            $this->notifylog($data,'notify-pay_status');
                        }
                    }else{
                        $this->notifylog($data,'notify-id');
                    }
                }else{
                    $this->notifylog($data,'notify-number');
                }
            }else{
                $this->notifylog($data,'notify-SUCCESS');
            }
        }else{
            $this->notifylog($data,'notify-isset');
        }

        echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        exit;
    }

    /*
    *支付宝下单
    */
    public function actionAddaliorder(){
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $contacts = Cm::$req->post('contacts', ['null', 'empty', 'default' => '']);
        $contacts_num = (int)Cm::$req->post('contacts_num', ['null', 'empty', 'default' => 0]);
        $contactsarr = empty($contacts) ? [] : json_decode($contacts,true);
        if(empty($contactsarr)){
            Cm::$res->error("请添加乘客信息");
        }
        if($contacts_num != count($contactsarr)){
            Cm::$res->error("乘客人数信息错误");
        }
        $time = time();
        $timestr = date("Y-m-d H:i:s",$time);
        $shiftinfo = Cm::$db->one("SELECT a.id,a.circuit_id,a.presaletime,a.closingtime,a.ticket_price,b.name FROM shift a INNER JOIN circuit b ON a.circuit_id=b.id WHERE a.id={$id} AND a.status=1 AND b.status=1");
        if(empty($shiftinfo)){
            Cm::$res->error("没有找到该班次");
        }
        if(strtotime($shiftinfo['closingtime'])<$time){
            Cm::$res->error("该班次已停售");
        }
        $user = Cm::$db->one("SELECT id,telephone FROM user WHERE openid='{$this->openid}'");
        if(empty($user['id'])){
            Cm::$res->error('参数错误');
        }
        $isok = 1;
        $telephone = '';
        $contactsids = [];
        $isrepeat = 0;
        foreach ($contactsarr as $key => $value) {
            if(empty($value['name']) || empty($value['telephone']) || empty($value['idcard']) || empty($value['id']) || empty($value['contacts_id'])){
                $isok = 0;
                break;
            }
            if(!in_array($value['contacts_id'], $contactsids)){
                $contactsids[] = $value['contacts_id'];
            }else{
                $isrepeat = 1;
                break;
            }
            $telephone = $key == 0 ? $value['telephone'] : $telephone;
        }
        if($isok == 0){
            Cm::$res->error('乘客信息不正确');
        }
        if($isrepeat == 1){
            Cm::$res->error('不能重复添加乘客');
        }

        $config = Cm::$db->all("SELECT `key`,`value` FROM config_setting WHERE `group`='sys' AND `key` IN ('sys_service_charge','sys_premium') ");
        $service_charge = 0;
        $premium = 0;
        if(!empty($config)){
            foreach ($config as $key => $vs) {
                if($vs['key'] == 'sys_service_charge'){
                    $service_charge = floatval($vs['value']*$contacts_num);
                }else if($vs['key'] == 'sys_premium'){
                    $premium = floatval($vs['value']*$contacts_num);
                }
            }
        }
        $price = floatval($shiftinfo['ticket_price']*$contacts_num);
        $order_price = $price + $premium + $service_charge;

        $order_number = $this->getorderanumber($id,$shiftinfo['circuit_id'],$timestr);
        $order_number = "M".$order_number;
        $orderdata = [
            'order_number' => $order_number,
            'shift_id'=> $id,
            'circuit_id' => $shiftinfo['circuit_id'],
            'order_status' => 0,
            'ridership' => count($contactsarr),
            'order_price' => $order_price,
            'price' => $price,
            'premium' => $premium,
            'service_charge' => $service_charge,
            'source' => 1,
            'user_id' => $user['id'],
            'user_telephone' => empty($user['telephone']) ? $telephone : $user['telephone'],
            'status'=>1,
            'addtime' => $timestr,
            'updatetime' => $timestr
        ];
        $orderid = Cm::$db->insert("order", $orderdata);

        $config = Yii::$app->params['alipay'];
        $config['notify_url'] = BASE_URL . Url::to(['/wechat/order/alinotify']);
        $config['public_key'] = $this->getPublicKey($config['app_cert']);
        $goods = [
            'out_trade_no' => $order_number,
            'total_amount' => $order_price,
            'subject' => $shiftinfo['name']
        ];
        $apihtml = Cm::$libs->wechat->alipay($config,$goods);

        if($orderid){
            foreach ($contactsarr as $key => $value) {
                $mdata = [
                    'order_id'=> $orderid,
                    'shift_id'=> $id,
                    'circuit_id' => $shiftinfo['circuit_id'],
                    'user_id'=> $user['id'],
                    'contacts_id' => $value['contacts_id'],
                    'name' => $value['name'],
                    'telephone' => $value['telephone'],
                    'id_card' => $value['idcard'],
                    'status' => 1,
                    'addtime' => $timestr,
                    'updatetime' => $timestr
                ];
                Cm::$db->insert("order_passenger", $mdata);
            }
            $this->addordercode($orderid);
            Cm::$res->susess(['id'=>$orderid,'order_number'=>$order_number,'price'=>$price,'order_price'=>$order_price,'premium'=>$premium,'service_charge'=>$service_charge,'html' => $apihtml],'保存成功');
        }else{
            Cm::$res->error('保存失败');
        }
    }

    /**
     * 从证书中提取公钥
     * @param $certPath
     * @return mixed
     */
    private function getPublicKey($certPath)
    {
        $cert = file_get_contents($certPath);
        $pkey = openssl_pkey_get_public($cert);
        $keyData = openssl_pkey_get_details($pkey);
        $public_key = str_replace('-----BEGIN PUBLIC KEY-----', '', $keyData['key']);
        $public_key = trim(str_replace('-----END PUBLIC KEY-----', '', $public_key));
        $public_key = preg_replace(['/\s+/', '/\-{5}.*?\-{5}/'], '', $public_key);
        return $public_key;
    }

    /*
    *待支付宝支付
    */
    public function actionPayaliorder(){
        $this->refreshorder();
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $where = " a.id={$id} AND u.openid='{$this->openid}'";
        $info = Cm::$db->one("SELECT a.id,a.order_number,a.order_price,a.order_status,a.status,c.name,a.pay_status
				FROM `order` a 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where}");
        if(empty($info)){
            Cm::$res->error("订单不存在");
        }
        if($info['order_status'] == 5){
            Cm::$res->error("订单已失效,无法在支付");
        }
        if($info['status'] != 1){
            $strarr = [0=>'取消',2=>'删除',3=>'改签',4=>'退款'];
            Cm::$res->error("订单已".$strarr[$info['status']].",无法在支付");
        }
        if($info['order_status'] != 0){
            Cm::$res->error("订单已支付,无法在支付");
        }

        if($info['pay_status'] != 0){
            Cm::$res->error("订单已支付,无法在支付");
        }

        $config = Yii::$app->params['alipay'];
        $config['notify_url'] = BASE_URL . Url::to(['/wechat/order/alinotify']);
        $config['public_key'] = $this->getPublicKey($config['app_cert']);
        $goods = [
            'out_trade_no' => $info['order_number'],
            'total_amount' => $info['order_price'],
            'subject' => $info['name']
        ];
        $apihtml = Cm::$libs->wechat->alipay($config,$goods);

        Cm::$res->susess(['html' => $apihtml],'');
    }

    /*
    *支付宝回调
    */
    public function actionAlinotify(){
        $this->notifylog($_POST,'ali-notify');
        $config = Yii::$app->params['alipay'];
        $config['notify_url'] = BASE_URL . Url::to(['/wechat/order/alinotify']);
        $config['public_key'] = $this->getPublicKey($config['app_cert']);
        $data = Cm::$libs->wechat->alinotify($config);
        if(empty($data['msg']) || $data['trade_status'] == 'TRADE_SUCCESS'){
            $this->notifylog($data,'ali-notify-sign-success');
            if($data['trade_status'] == 'TRADE_SUCCESS'){
                $number = isset($data['out_trade_no']) ? $data['out_trade_no'] : '';
                if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,pay_status FROM `order` WHERE order_number='{$number}' AND pay_status=0");
                    if (isset($info['id'])) {
                        if ($info['pay_status']==0) {
                            //更改支付状态
                            $time = date("Y-m-d H:i:s",time());
                            Cm::$db->update("order", ["order_status"=>1,"updatetime"=>$time,"pay_type"=>2,"pay_status" => 1, "pay_time" => $time,'pay_price'=>$data['total_amount']], "id={$info['id']}");

                            //发送购买成功通知
                            $TemplateData = [
                                'openid' => $data['openid'],
                                'order_id' => $info['id']
                            ];
                            Cm::$libs->wechat->sendTemplate('order',$TemplateData);
                            echo "success";
                        }else{
                            $this->notifylog($data,'ali-notify-pay_status');
                        }
                    }else{
                        $this->notifylog($data,'ali-notify-id');
                    }
                }else{
                    $this->notifylog($data,'ali-notify-number');
                }
            }else{
                $this->notifylog($data,'ali-notify-pay-fail');
            }
        }else{
            $this->notifylog($data,'ali-notify-sign-fail');
        }
        echo "fail";
    }

    /*
    *获取我的订单
    */
    public function actionOrderlist(){
        $this->refreshorder();
        $page = Cm::$req->post('page', ['null', 'empty', 'default' => 1]);
        $limit = Cm::$req->post('limit', ['null', 'empty', 'default' => 10]);
        $type = Cm::$req->post('type', ['null', 'empty', 'default' => 0]);
        $where = " a.status!=2 AND u.openid='{$this->openid}'";
        $time = time();
        $nowtime = date("Y-m-d H:i:s",$time);
        $time15 = $time+900;
        $etime = date("Y-m-d H:i:s",$time+900);
        if($type == 1){
            $where .= " AND a.order_status=0 ";
        }elseif($type == 2){
            $where .= " AND (a.order_status=1 OR (a.order_status=2 && b.departuretime>'{$etime}') ) ";
        }elseif($type == 3){
            $where .= " AND a.order_status IN (3,4) ";
        }elseif($type == 4){
            $where .= " AND a.order_status=5";
        }elseif($type == 5){
            $where .= " AND a.order_status=5 AND a.status=4";
        }elseif ($type == 6) {
            $where .= " AND a.order_status=2 AND b.departuretime>='{$nowtime}' AND b.departuretime<='{$etime}' ";
        }
        $sql = "SELECT a.id,a.order_number,a.order_price,a.order_status,a.status,coa.name,a.s_id,a.e_id,a.p_id,coa.name AS citysname,c.s_address,c.e_address,coa.id AS citysid,cob.name AS cityename,cob.id AS cityeid,sa.name AS sitesname,sa.id AS sitesid,sb.name AS siteename,sb.id AS siteeid,b.departuretime,ridership AS ticketnum,a.circuit_id,a.codeimg,a.codenum,a.refund_status
				FROM `order` a 
				LEFT JOIN shift b ON a.shift_id=b.id 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN open_city coa ON coa.code=c.city_scode 
				LEFT JOIN open_city cob ON cob.code=c.city_ecode
				LEFT JOIN site sa ON sa.id=c.site_sid 
				LEFT JOIN site sb ON sb.id=c.site_eid 
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where} ORDER BY a.id DESC,a.order_status ASC,b.departuretime ASC";
        $resdata = Cm::$db->paging($sql,$page, $limit);
        $s_id=array_column($resdata['data'],'s_id');
        $e_id=array_column($resdata['data'],'e_id');
        $ids=array_merge($e_id,$s_id);
        $pt_ids=array_filter(array_unique(array_column($resdata['data'],'p_id')));
        $departuretime=[];
        if(count($pt_ids)){
            $departuretime=PointTime::find()->andWhere(['id'=>$pt_ids])->select(['departuretime'])->indexBy('id')->column();
        }
        $address=CircuitAddress::find()->alias('ca')
            ->leftJoin(['s'=>Site::tableName()],['ca.site_id'=>new Expression('s.id')])
            ->andWhere(['ca.id'=>$ids])
            ->select(['s.name','ca.id'])
            ->indexBy('id')->column();
        foreach ($resdata['data'] as $key => &$value) {
            if(strtotime($departuretime[$value['p_id']]??0)>strtotime($value['departuretime'])){
                $value['departuretime']=$departuretime[$value['p_id']];
            }
            $departuretime = strtotime($value['departuretime']);
            if($value['order_status'] == 2 && $departuretime>=$time && $departuretime<= $time15){
                $value['order_status'] = 6;
            }
            $value['day'] = date("m月d日",$departuretime);
            $value['hour'] = date("H:i",$departuretime);
            $exitchange = $this->checkchange($value['id'],$value['departuretime'],$nowtime,$value['circuit_id']);
            $value['ischange'] = $exitchange['status'] == 1 && in_array($value['order_status'], [1,2]) && $value['status']==1 ? 1:0;
            if(empty($value['codeimg']) && $value['order_status'] != 0 && $value['order_status'] !=5){
                $codedata = $this->addordercode($value['id']);
                $value['codeimg'] = $codedata['codeimg'];
                $value['codenum'] = $codedata['codenum'];
            }
            $value['codeimg'] = empty($value['codeimg']) ? '' : $value['codeimg'];
//            if($value['s_id']&&$value['e_id']){
                $value['s_address']=$address[$value['s_id']]??$value['s_address'];
//                $value['e_address']=$address[$value['e_id']]??'';
//            }
        }
        Cm::$res->susess($resdata);
    }

    /*
    *取消订单
    */
    public function actionCancel(){
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $order = Cm::$db->one("SELECT id,status,order_status FROM `order` WHERE id={$id}");
        if(empty($order)){
            Cm::$res->error("订单不存在");
        }
        if($order['status'] == 1 && $order['order_status'] == 0){
            $time = date("Y-m-d H:i:s",time());
            $mdata = [
                'status' => 0,
                'order_status' => 5,
                'updatetime' => $time,
                'canceltime' => $time
            ];
            Cm::$db->update("order", $mdata," id={$id}");
            Cm::$res->susess([],"取消订单成功");
        }else{
            $msg = '';
            if($order['status'] == 1){
                switch ($order['order_status']) {
                    case 1:
                        $msg = "订单已支付";
                        break;
                    case 2:
                        $msg = "订单已支付";
                        break;
                    case 3:
                        $msg = "订单已发车";
                        break;
                    case 4:
                        $msg = "订单已完成";
                        break;
                }
            }else if($order['status'] == 2){
                $msg = "订单已删除";
            }else if($order['status'] == 0){
                $msg = "订单已取消";
            }else if($order['status'] == 3){
                $msg = "订单已改签";
            }else if($order['status'] == 4){
                $msg = "订单已退款";
            }
            $msg .= $msg==''?'订单当前状态不能进行取消操作':",不能在进行取消操作";
            Cm::$res->error($msg);
        }
    }

    /*
    *订单详情
    */
    public function actionInfo(){
        $this->refreshorder();
        $id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
        $where = " a.id={$id} AND u.openid='{$this->openid}'";
        $info = Cm::$db->one("SELECT a.id,a.order_number,a.circuit_id,a.order_price,a.price,a.premium,a.service_charge,a.order_status,a.status,a.s_id,a.e_id,a.p_id,b.type,c.mileage,coa.name AS citysname,coa.id AS citysid,cob.name AS cityename,cob.id AS cityeid,sa.name AS sitesname,sa.id AS sitesid,sb.name AS siteename,sb.id AS siteeid,b.departuretime,a.codenum,a.codeimg,a.refund_status,c.s_address,c.e_address 
				FROM `order` a 
				LEFT JOIN shift b ON a.shift_id=b.id 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN open_city coa ON coa.code=c.city_scode 
				LEFT JOIN open_city cob ON cob.code=c.city_ecode
				LEFT JOIN site sa ON sa.id=c.site_sid 
				LEFT JOIN site sb ON sb.id=c.site_eid 
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where}");
        if(empty($info)){
            Cm::$res->error("订单不存在");
        }
        $config = Cm::$db->all("SELECT `key`,`value` FROM config_setting WHERE `group`='sys' AND `key` IN ('sys_service_charge','sys_premium') ");
        $service_charge = 0;
        $premium = 0;
        if(!empty($config)){
            foreach ($config as $key => $vs) {
                if($vs['key'] == 'sys_service_charge'){
                    $service_charge = floatval($vs['value']);
                }else if($vs['key'] == 'sys_premium'){
                    $premium = floatval($vs['value']);
                }
            }
        }
        $info['one_service_charge'] = $service_charge;
        $info['one_premium'] = $premium;
        $departuretime=PointTime::find()->andWhere(['id'=>$info['p_id']])->select(['departuretime'])->indexBy('id')->column();
        if(strtotime($departuretime[$info['p_id']]??0)>strtotime($info['departuretime'])){
            $value['departuretime']=$departuretime[$info['p_id']];
        }
        $departuretime = strtotime($info['departuretime']);
        $info['day'] = date("m月d日",$departuretime);
        $info['hour'] = date("H:i",$departuretime);
        $info['typestr'] = $info['type'] == 1 ? "固定班":"流动班";
        if($info['s_id']&&$info['e_id']){
            $site_ids=CircuitAddress::find()
                ->andWhere(['id'=>[$info['s_id'],$info['e_id']]])
                ->select('site_id')
                ->indexBy('id')
                ->column();
            $info['s_address']=CircuitAddress::findOne($info['s_id'])->address;
            $info['s_site']=Site::find()->andWhere(['id'=>$site_ids[$info['s_id']]])->select('name as address')->scalar();
            $info['e_site']=Site::find()->andWhere(['id'=>$site_ids[$info['e_id']]])->select('name as address')->scalar();
        }
        $passenger = Cm::$db->all("SELECT name,telephone,id_card AS idcard,seat_number FROM order_passenger WHERE order_id={$id} AND status=1");
        $seat_number = [];
        foreach ($passenger as $key => &$value) {
            $idcardlen = strlen($value['idcard']);
            $value['idcard'] = $idcardlen==15?substr_replace($value['idcard'],"******",4,6):($idcardlen==18?substr_replace($value['idcard'],"*********",4,9):$value['idcard']);
            if(!empty($value['seat_number'])){
                $seat_number[] = $value['seat_number']."号";
            }
        }
        $car = Cm::$db->one("SELECT b.plate,c.username AS name,c.account AS telephone FROM order_car a
							LEFT JOIN car b ON b.id=a.car_id
							LEFT JOIN sys_manager c ON c.id=a.inspector
							WHERE a.order_id={$id} AND a.status=1");
        if(!empty($seat_number)){
            $car['seat_number'] = implode("  ", $seat_number);
        }
        $car = empty($car) ? [] : $car;
        $exitchange = $this->checkchange($info['id'],$info['departuretime'],date("Y-m-d H:i:s",time()),$info['circuit_id']);
        $info['ischange'] = $exitchange['status'] == 1 && in_array($info['order_status'], [1,2]) && $info['status']==1? 1:0;
        Cm::$res->susess(['info'=>$info,'passenger'=>$passenger,'car'=>$car]);
    }

    /*
    *订单改签提交审核
    */
    public function actionChange(){
        $order_id = (int)Cm::$req->post('order_id', ['null', 'empty', 'default' => 0]);
        $shift_id = (int)Cm::$req->post('shift_id', ['null', 'empty', 'default' => 0]);
        $pt_id = (int)Cm::$req->post('pt_id', ['null', 'empty', 'default' => 0]);
        $order = Cm::$db->one("SELECT a.id,a.order_status,a.status,b.departuretime,a.circuit_id FROM `order` a LEFT JOIN shift b ON b.id=a.shift_id WHERE a.id={$order_id}");
        if(empty($order)){
            Cm::$res->error("订单未找到");
        }
        if($order['status'] == 1 && in_array($order['order_status'], [1,2])){
            $time = date("Y-m-d H:i:s",time());
            /*改签规则验证*/
            $exitchange = $this->checkchange($order['id'],$order['departuretime'],$time,$order['circuit_id']);
            if($exitchange['status'] == 0){
                $str = $exitchange['time'] == 0 ? "" : "发车前".$exitchange['time']."分钟";
                Cm::$res->error("订单".$str."无法进行改签操作");
            }else if($exitchange['status'] == 3){
                Cm::$res->error("该订单行程已达到系统设置的最大改签次数".$exitchange['changenum']."次,无法进行改签操作");
            }

            $mdata = [
                'order_id' => $order_id,
                'shift_id' => $shift_id,
                'first_order_id' => empty($exitchange['order_id']) ? $order_id : $exitchange['order_id'],
                'status' => 1,
                'addtime' => $time,
                'updatetime' => $time
            ];
            $id = Cm::$db->insert("order_change_audit", $mdata);
            if($id){
                /*生成新订单*/
                $this->addneworder($id,$time,$pt_id);
                Cm::$res->susess([],"改签成功");
            }else{
                Cm::$res->error("改签失败");
            }
        }else{
            $msg = '';
            if($order['status'] == 1){
                switch ($order['order_status']) {
                    case 0:
                        $msg = "订单未支付";
                        break;
                    case 3:
                        $msg = "订单已发车";
                        break;
                    case 4:
                        $msg = "订单已完成";
                        break;
                }
            }else if($order['status'] == 2){
                $msg = "订单已删除";
            }else if($order['status'] == 0){
                $msg = "订单已取消";
            }else if($order['status'] == 3){
                $msg = "订单已改签";
            }else if($order['status'] == 4){
                $msg = "订单已退款";
            }
            $msg .= $msg==''?'订单当前状态不能进行改签操作':",不能在进行改签操作";
            Cm::$res->error($msg);
        }
    }

    /*
    *订单退款
    */
    public function actionRefund(){
        $order_id = (int)Cm::$req->post('order_id', ['null', 'empty', 'default' => 0]);
        $time = time();
        $order = Cm::$db->one("SELECT a.id,a.order_number,a.order_status,a.status,b.departuretime,a.circuit_id,a.pay_price,a.pay_type 
								FROM `order` a 
								LEFT JOIN shift b ON b.id=a.shift_id 
								LEFT JOIN user u ON u.id=a.user_id 
								WHERE a.id={$order_id} AND u.openid='{$this->openid}'");
        if(empty($order)){
            Cm::$res->error("订单不存在");
        }
        if($order['status'] == 1 && in_array($order['order_status'], [1,2]) ){
            $timestr = date("Y-m-d H:i:s",$time);
            /*验证能否进行退票*/
            $exitisok = $this->checkrefund($order['departuretime'],$timestr,$order['circuit_id']);
            if($exitisok['status'] == 0){
                $str = $exitisok['time'] == 0 ? "" : "发车前".$exitisok['time']."分钟";
                Cm::$res->error("订单".$str."无法进行退票操作");
            }
            /*是否有改签*/
            $haschange = $this->ischangeorder($order['id']);
            $order['pay_price'] = $haschange['status'] == 1 ? $haschange['pay_price'] : $order['pay_price'];
            $departuretime = strtotime($order['departuretime']);
            /*全款退*/
            $isall = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=6 AND  circuit_id={$order['circuit_id']} AND status=1");
            if(empty($isall)){
                $isall = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=6 AND  circuit_id=0 AND status=1");
                $alltimenum = empty($isall) ? 0 : (int)$isall['value'];
            }else{
                $alltimenum = (int)$isall['value'];
            }
            $isok = 0;
            $refund_amount = $order['pay_price'];
            $refund_service = 0;
            if($alltimenum != 0){
                $alltime = strtotime("-".$alltimenum." day",$departuretime);
                if($time <= $alltime){
                    /*全款退*/
                    $isok = 1;
                }
            }

            /*部分退*/
            if($isok == 0){
                /*部分*/
                $isone = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=8 AND  circuit_id={$order['circuit_id']} AND status=1");
                if(empty($isone)){
                    $isone = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=8 AND  circuit_id=0 AND status=1");
                }
                if(!empty($isone)){
                    $rule = json_decode($isone['value'],true);
                    foreach ($rule['start'] as $key => $value) {
                        $starttime = $value == 0 ?  $departuretime : strtotime("-".$value." day",$departuretime);
                        $endtime = strtotime("-".$rule['end'][$key]." day",$departuretime);
                        $service = $rule['service'][$key];
                        if($time >= $endtime && $time < $starttime) {
                            $isok = 1;
                        }
                        if($isok == 1){
                            $refund_service = sprintf("%.2f",$refund_amount*$service/100);
                            $refund_amount = $refund_service > 0 ? sprintf("%.2f",$refund_amount-$refund_service) : $refund_amount;
                            if($refund_amount>$order['pay_price']){
                                $refund_amount = $order['pay_price'];
                                $refund_service = 0;
                            }
                            break;
                        }
                    }
                }
            }
            $order['order_number'] = $haschange['status'] == 1 ? $haschange['order_number'] : $order['order_number'];
            /*退款单号*/
            $refund_number = "R".$order['order_number'];
            if($order['pay_type'] == 1){
                $config = Yii::$app->params['wechat']['open'];
                $paySdk = Cm::$libs->wechat->pay($config['appid']);
                $goods = [
                    "out_trade_no" => $order['order_number'],
                    "out_refund_no" => $refund_number,
                    "refund_fee" => $refund_amount*100,
                    "total_fee" => $order['pay_price'] * 100,
                    "notify_url" => BASE_URL . Url::to(['/wechat/order/refundnotify'])
                ];
                $res = $paySdk->orderrefund($goods);
                $refund_status = 0;
            }else{
                $config = Yii::$app->params['alipay'];
                $config['public_key'] = $this->getPublicKey($config['app_cert']);
                $goods = [
                    'out_trade_no' => $order['order_number'],
                    'refund_amount' => $refund_amount
                ];
                $result = Cm::$libs->wechat->alirefund($config,$goods);
                $res = array("flag" => false, "msg" => "", "data" => array());
                Cm::$app->log->common('alirefund', $result);
                if($result['code'] == 10000 && $result['msg'] == 'Success'){
                    $res['flag'] = true;
                    $refund_status = 1;
                }else{
                    $res['msg'] = $result['sub_msg'];
                }

            }
            if($res['flag']){
                $mdata = [
                    'status' => 4,
                    'order_status' => 5,
                    'updatetime' => $timestr,
                    'refund_amount' => $refund_amount,
                    'refund_service' => $refund_service,
                    'refund_number' => $refund_number,
                    'refund_time' => $timestr,
                    'refund_status' => $refund_status
                ];
                Cm::$db->update("order", $mdata," id={$order_id}");
                if($order['pay_type'] == 2){
                    //发送退款成功通知
                    $TemplateData = [
                        'order_id' => $order_id,
                    ];
                    Cm::$libs->wechat->sendTemplate('refund',$TemplateData);
                }
                Cm::$res->susess([],"退款申请成功");
            }else{
                Cm::$res->error($res['msg']);
            }
        }else{
            $msg = '';
            if($order['status'] == 1){
                switch ($order['order_status']) {
                    case 0:
                        $msg = "订单未支付";
                        break;
                    case 3:
                        $msg = "订单已发车";
                        break;
                    case 4:
                        $msg = "订单已完成";
                        break;
                }
            }else if($order['status'] == 2){
                $msg = "订单已删除";
            }else if($order['status'] == 0){
                $msg = "订单已取消";
            }else if($order['status'] == 3){
                $msg = "订单已改签";
            }else if($order['status'] == 4){
                $msg = "订单已退款";
            }
            $msg .= $msg==''?'订单当前状态不能进行退款操作':",不能在进行退款操作";
            Cm::$res->error($msg);
        }
    }

    /*退票回调*/
    public function actionRefundnotify(){
        $xml = file_get_contents('php://input');
        $this->notifylog($xml,'refundnotify-input');

        if (empty($xml)) {
            $this->notifylog("支付回调无参数","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!$data) {
            $this->notifylog("没有数据","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        if($data['return_code'] == 'SUCCESS'){
            $req_info_xml = $this->refundDecrypt($data['req_info']);
            libxml_disable_entity_loader(true);
            $reqinfoarr = json_decode(json_encode(simplexml_load_string($req_info_xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            if($reqinfoarr['refund_status'] == 'SUCCESS'){
                $number = isset($reqinfoarr['out_refund_no']) ? $reqinfoarr['out_refund_no'] : '';
                if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,refund_status FROM `order` WHERE refund_number='{$number}' AND refund_status=0");
                    if (isset($info['id'])) {
                        if ($info['refund_status']==0) {
                            //更改退款状态
                            $time = isset($reqinfoarr['success_time']) ? $reqinfoarr['success_time'] : date("Y-m-d H:i:s",time());
                            Cm::$db->update("order", ["refund_status"=>1,"refund_time"=>$time], "id={$info['id']}");
                            if(($model=UserRebate::find()->andWhere(["order_id"=>$info['id'],'status'=>UserRebate::STATUS_PASS])->one())){
                                $model->status=UserRebate::STATUS_CANCEL;
                                if($model->save())LogHelper::Logging(Yii::getAlias("@common/runtime/佣金在途修改撤销失败/" . date("Ymd") . ".txt"), Json::encode($info));
                            }
                            //发送退款成功通知
                            $TemplateData = [
                                'order_id' => $info['id'],
                            ];
                            Cm::$libs->wechat->sendTemplate('refund',$TemplateData);
                        }else{
                            $this->notifylog($reqinfoarr,'refundnotify-refund_status');
                        }
                    }else{
                        $this->notifylog($reqinfoarr,'refundnotify-id');
                    }
                }else{
                    $this->notifylog($reqinfoarr,'refundnotify-number');
                }
            }else{
                $this->notifylog("没有数据","refundnotify-req_info");
            }
            echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            exit;
        }else{
            $this->notifylog("没有数据","refundnotify-FAIL");
        }
        echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
        exit;
    }

    /*后台退票回调*/
    public function actionRefundnotify2(){
        $xml = file_get_contents('php://input');
        $this->notifylog($xml,'refundnotify-input');

        if (empty($xml)) {
            $this->notifylog("支付回调无参数","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!$data) {
            $this->notifylog("没有数据","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        if($data['return_code'] == 'SUCCESS'){
            $req_info_xml = $this->refundDecrypt($data['req_info']);
            libxml_disable_entity_loader(true);
            $reqinfoarr = json_decode(json_encode(simplexml_load_string($req_info_xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            if($reqinfoarr['refund_status'] == 'SUCCESS'){
                $number = isset($reqinfoarr['out_refund_no']) ? $reqinfoarr['out_refund_no'] : '';
                if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,refund_status FROM `order` WHERE refund_number='{$number}' AND refund_status=0");
                    if (isset($info['id'])) {
                        if ($info['refund_status']==0) {
                            //更改退款状态
                            $time = isset($reqinfoarr['success_time']) ? $reqinfoarr['success_time'] : date("Y-m-d H:i:s",time());
                            Cm::$db->update("order", ["refund_status"=>1,"refund_time"=>$time], "id={$info['id']}");
                            if(($model=UserRebate::find()->andWhere(["order_id"=>$info['id'],'status'=>UserRebate::STATUS_PASS])->one())){
                                $model->status=UserRebate::STATUS_CANCEL;
                                if($model->save())LogHelper::Logging(Yii::getAlias("@common/runtime/佣金在途修改撤销失败/" . date("Ymd") . ".txt"), Json::encode($info));
                            }
                            //发送退款成功通知
                            $TemplateData = [
                                'order_id' => $info['id'],
                            ];
                            Cm::$libs->wechat->sendTemplate('refund2',$TemplateData);
                        }else{
                            $this->notifylog($reqinfoarr,'refundnotify-refund_status');
                        }
                    }else{
                        $this->notifylog($reqinfoarr,'refundnotify-id');
                    }
                }else{
                    $this->notifylog($reqinfoarr,'refundnotify-number');
                }
            }else{
                $this->notifylog("没有数据","refundnotify-req_info");
            }
            echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            exit;
        }else{
            $this->notifylog("没有数据","refundnotify-FAIL");
        }
        echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
        exit;
    }

    /*
    *改签生成新的订单
    */
    private function addneworder($auditid,$time,$pt_id=0){
        $order = Cm::$db->one("SELECT a.shift_id,b.circuit_id,b.ridership,b.order_price,b.price,b.premium,b.service_charge,b.source,b.user_id,b.user_telephone,b.id as order_id,b.order_status,b.status,
       b.pay_type,b.pay_time,b.pay_price,b.pay_status,b.rebate_status,b.rebate_type,b.rebate,b.rebate_price,b.rebate_issue,b.bind_uid,b.s_id,b.e_id,b.p_id
                            FROM order_change_audit a 
                            LEFT JOIN `order` b ON b.id=a.order_id 
                            WHERE a.id={$auditid}");
        $contactsarr = Cm::$db->all("SELECT b.* FROM order_change_audit a LEFT JOIN order_passenger b ON b.order_id=a.order_id WHERE a.id={$auditid}");
        if(empty($contactsarr)){
            Cm::$db->delete("order_change_audit","id={$auditid}");
            Cm::$res->error("改签失败,没有找打乘客信息");
        }
        $order_id = $order['order_id'];
        unset($order['order_id']);
        $order['order_status'] = 1;
        $order['status'] = 1;
        $order['addtime'] = $time;
        $order['updatetime'] = $time;
        if($pt_id)$order['p_id']=$pt_id;
        $order_number = $this->getorderanumber($order['shift_id'],$order['circuit_id'],$time);
        $order['order_number'] = "M".$order_number;
        $changeid = Cm::$db->insert("order", $order);
        if($changeid){
            $this->addordercode($changeid);
            Cm::$db->update("order",['order_status'=>5,'status'=>3,'updatetime'=> $time],"id={$order_id}");
            if(($model=UserRebate::find()->andWhere(["order_id"=>$order_id,'status'=>UserRebate::STATUS_PASS])->one())){
                $model->status=UserRebate::STATUS_CANCEL;
                if($model->save())LogHelper::Logging(Yii::getAlias("@common/runtime/佣金在途修改撤销失败/" . date("Ymd") . ".txt"), Json::encode(['改签订单id'=>$order_id]));
                if($order['bind_uid']&&$order['rebate_status']==Order::REBATE_STATUS_YES&&$order['rebate_price']>0
                    &&!UserRebate::find()->andWhere(['order_id'=>$changeid])->exists()){
                    $model=new UserRebate();
                    $model->uid=$order['bind_uid'];
                    $model->type=UserRebate::TYPE_GET;
                    $model->order_id=$changeid;
                    $model->money=$order['rebate_price'];
                    $model->date_ym=date("Ym",time());
                    $model->date_ymd=date("Ymd",time());
                    $model->status=UserRebate::STATUS_PASS;
                    if(!$model->save())LogHelper::Logging(Yii::getAlias("@common/runtime/佣金在途失败/" . date("Ymd") . ".txt"), Json::encode($order));
                }

            }
            Cm::$db->update("order_passenger",['status'=>0,'updatetime'=> $time],"order_id={$order_id}");
            foreach ($contactsarr as $key => $value) {
                $mdata = [
                    'order_id'=> $changeid,
                    'shift_id'=> $order['shift_id'],
                    'circuit_id' => $order['circuit_id'],
                    'user_id'=> $value['user_id'],
                    'contacts_id' => $value['contacts_id'],
                    'name' => $value['name'],
                    'telephone' => $value['telephone'],
                    'id_card' => $value['id_card'],
                    'status' => 1,
                    'addtime' => $time,
                    'updatetime' => $time
                ];
                Cm::$db->insert("order_passenger", $mdata);
            }
            Cm::$db->update("order_change_audit",['change_id'=>$changeid,'updatetime'=> $time],"id={$auditid}");
            /*发送模板消息*/
            $TemplateData = [
                'openid' => $this->openid,
                'old_order_id' => $order_id,
                'changeid' => $changeid,
            ];
            Cm::$libs->wechat->sendTemplate('change',$TemplateData);
        }else{
            Cm::$db->delete("order_change_audit","id={$auditid}");
            Cm::$res->error("改签失败,无法生成新订单");
        }
    }

    /*
    *解密
    */
    private function refundDecrypt($str){
        $decrypt = base64_decode($str,true);
        $config = Yii::$app->params['wechat']['open'];
        $key = md5($config['mch_key']);
        return openssl_decrypt($decrypt, 'aes-256-ecb', $key , OPENSSL_RAW_DATA);
    }

    /*
    *检验是否能退款
    */
    private function checkrefund($departuretime,$nowtime,$circuit_id){
        /*是否能退票*/
        $isok = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=7 AND  circuit_id={$circuit_id} AND status=1");
        if(empty($isok)){
            $isok = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=7 AND circuit_id=0 AND status=1");
            $time = empty($isok) ? 0 : (int)$isok['value'];
        }else{
            $time = (int)$isok['value'];
        }
        $departuretime = strtotime($departuretime);
        $checktime = $departuretime-$time*60;
        $nowtime = strtotime($nowtime);
        return  ['status'=>$nowtime >= $departuretime || $nowtime >= $checktime ? 0 : 1,'time'=>$time];
    }

    /*
    *检验是否能进行改签
    */
    private function checkchange($order_id,$departuretime,$nowtime,$circuit_id){
        $haschange = $this->ischangeorder($order_id);
        if($haschange['status'] == 1){
            /*改签上限*/
            $ishas = Cm::$db->one("SELECT * FROM config_setting WHERE `group`='sys' AND `key`='sys_order_change' AND status=1");
            $changenum = empty($ishas) ? 0 : $ishas['value'];
            if($changenum > 0 && $changenum<=$haschange['changenum']){
                return ['status'=>3,'time'=>'','changenum' =>$haschange['changenum']];
            }
        }
        $exitchange = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=5 AND  circuit_id={$circuit_id} AND status=1");
        if(empty($excicuit)){
            $exitchange = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=5 AND circuit_id=0 AND status=1");
            $time = empty($exitchange) ? 0 : (int)$exitchange['value'];
        }else{
            $time = (int)$exitchange['value'];
        }
        $departuretime = strtotime($departuretime);
        $checktime = $departuretime-$time*60;
        $nowtime = strtotime($nowtime);
        return  ['status'=>$nowtime >= $departuretime || $nowtime >= $checktime ? 0 : 1,'time'=>$time,'order_id'=>$haschange['order_id']];
    }

    /*是否是改签新单*/
    private function ischangeorder($order_id){
        $haschange = Cm::$db->one("SELECT a.id,a.first_order_id AS order_id,(SELECT CONCAT_WS(',',order_number,pay_price) AS firstorder FROM `order` WHERE id=a.first_order_id) AS firstorder,(SELECT COUNT(id) AS num FROM order_change_audit WHERE first_order_id=a.first_order_id AND status=1) AS changenum FROM order_change_audit a WHERE a.change_id={$order_id} AND a.status=1");
        $firstorder = empty($haschange) ? '' : explode(",", $haschange['firstorder']);
        return ['status'=>empty($haschange) ? 0 : 1,'order_number' => empty($haschange) ? '' : $firstorder[0],'pay_price'=>empty($haschange) ? '' : $firstorder[1],'order_id' => empty($haschange) ? '' : $haschange['order_id'],'changenum'=>empty($haschange) ? 0 : $haschange['changenum']];
    }

    /*
    *生成订单号
    */
    private  function getorderanumber($shift_id,$circuit_id,$timestr){
        $sql = "SELECT order_number
		        FROM `order` 
				WHERE shift_id={$shift_id} AND circuit_id={$circuit_id}
				AND TO_DAYS(addtime)=TO_DAYS('{$timestr}') ORDER BY id DESC";
        $order = Cm::$db->one($sql);

        $order_number = "";
        $ctime = date('ymd', strtotime($timestr));
        if (isset($order['order_number'])) {
            $order_number = $order['order_number'];
            if (substr($order_number, 0, 1) == 'M') {
                $order_number = str_replace('M', '', $order_number);
            }
            $number =  (((int)substr($order_number, -4)) + 1);
            $order_number =  $shift_id . $circuit_id . $ctime .sprintf("%04d", $number);
        } else {
            $record_id = 1 % 10000;
            $order_number = $shift_id . $circuit_id . $ctime . sprintf("%04d", $record_id);
        }
        return $order_number;
    }

    /*
    *须知数据
    */
    private function getNoticeData($key){
        $sql = "SELECT value FROM config_setting WHERE `group`='sys' AND `key`='{$key}' AND  status=1";
        $data = Cm::$db->one($sql);
        $resdata = [];
        if(!empty($data)){
            $resdata = htmlspecialchars_decode(str_replace(array("\r\n", "\r", "\n"), "", $data['value']));
        }
        return $resdata;
    }

    /*
    *刷新订单
    */
    private function refreshorder(){
        $time = time();
        /*待支付的订单 更新已失效  1*/
        $this->changeorderstatus(1,$time,5);
        /*已支付的订单 更新已发车 3*/
        //$this->changeorderstatus(3,$time,3);
        /*已支付的订单 更新已完成 4*/
        //$this->changeorderstatus(4,$time,4);
    }

    /*更新订单状态*/
    private function changeorderstatus($type,$time,$status){
        $setting = Cm::$db->all("SELECT `value`,circuit_id FROM rule_setting WHERE type={$type} AND status=1");
        $timestr = date("Y-m-d H:i:s",$time);
        $where = $type == 1 ? " AND a.order_status=0 " : ($type==3?" AND a.order_status IN (1,2)" : " AND a.order_status IN (1,2,3) ");
        if(!empty($setting)){
            $settingarr = [];
            foreach ($setting as $key => $value) {
                $settingarr[$value['circuit_id']] = $value['value'];
            }
            $list = Cm::$db->all("SELECT a.id,a.addtime,a.circuit_id,b.departuretime FROM `order` a 
								LEFT JOIN user u ON u.id=a.user_id 
								LEFT JOIN shift b ON b.id=a.shift_id 
								WHERE u.openid='{$this->openid}' {$where} AND a.status=1");
            if(!empty($list)){
                foreach ($list as $key => $value) {
                    $setting_time = isset($settingarr[$value['circuit_id']]) ? $settingarr[$value['circuit_id']] : (isset($settingarr[0]) ? $settingarr[0] : 0);
                    $ordertime = $type==1 ? strtotime($value['addtime'])+$setting_time*60 : strtotime($value['departuretime'])+$setting_time*60;
                    if($setting_time != 0 && $ordertime<=$time){
                        $mdata = [
                            'order_status' => $status,
                            'updatetime' => $timestr
                        ];
                        Cm::$db->update("order",$mdata," id={$value['id']}");
                    }
                }
            }
        }
    }

    /*
    *添加二维码
    */
    public function addordercode($orderid){
        $codenum = Cm::$code->jia($orderid, true);
        $url = BASE_URL . Url::to(['/inspector/#/orderDetails', 'code' => urlencode($codenum)]);
        $codeimg = BASE_PATH."upload/ordercode/".$orderid.".png";
        Cm::$util->QRcode($url, 3.5, $codeimg);
        $codedata = [
            'codenum' => $codenum,
            'codeimg' => BASE_URL."/upload/ordercode/".$orderid.".png"
        ];
        Cm::$db->update("order",$codedata,"id={$orderid}");
        return $codedata;
    }

    /*
    *支付回调log
    */
    private function notifylog($data, $type = 'notify')
    {
        Cm::$app->log->common($type, $data);
    }

    /*
    *签名
    */
    private function checkSign($data)
    {
        $flag = false;

        if (isset($data['appid']) && isset($data['sign'])) {
            $config = Yii::$app->params['wechat']['open'];
            $mchKey = isset($config['mch_key']) ? $config['mch_key'] : '';

            ksort($data);
            $string = $this->ToUrlParams($data);
            //签名步骤二：在string后加入KEY
            $string = $string . "&key=" . $mchKey;
            //签名步骤三：MD5加密
            $string = md5($string);
            //签名步骤四：所有字符转为大写
            $makeSign = strtoupper($string);

            if ($data['sign'] == $makeSign)
                $flag = true;

        }

        $rowData = array(
            "out_trade_no" => isset($data['out_trade_no']) ? $data['out_trade_no'] : '',
            "appid" => isset($data['appid']) ? $data['appid'] : '',
            "openid" => isset($data['openid']) ? $data['openid'] : '',
            "cash_fee" => isset($data['cash_fee']) ? $data['cash_fee'] : '',
            "sign" => isset($data['sign']) ? $data['sign'] : '',
            "content" => json_encode($data),
            "check_sign" => $flag ? 1 : 0,
            "make_sign" => $makeSign,
            "addtime" => date('Y-m-d H:i:s')
        );
        $this->notifylog($rowData,'notify-checkSign');

        return $flag;
    }

    /**
     * 格式化参数格式化成url参数
     */
    private function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }
}